package com.lxq.springBoot.es;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestES {
	@Autowired
	private TransportClient client;
	
	@GetMapping("/")
	public String index() {
		return "你好";
	}

	@GetMapping("/get/book/novel/{id}")
	@ResponseBody
	public ResponseEntity get(@PathVariable(name = "id") String id) {
		GetResponse response = client.prepareGet("book", "novel", id).get();
		if (!response.isExists()) {
			return new ResponseEntity(HttpStatus.NOT_FOUND);
		}
		return new ResponseEntity(response.getSource(), HttpStatus.OK);
	}

	@PostMapping("add/book/novel")
	@ResponseBody
	public ResponseEntity add(@RequestParam("title") String title, @RequestParam("name") String name,
			@RequestParam("author") String author, @RequestParam("word_count") String word_count,
			@RequestParam("publish_date") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date publish_date) {
		try {
			XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().field("title", title)
					.field("name", name).field("author", author).field("word_count", word_count).endObject();
			IndexResponse indexResponse = client.prepareIndex("book", "novel").setSource(xContentBuilder).get();
			return new ResponseEntity(indexResponse, HttpStatus.OK);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	@DeleteMapping("del/book/novel/{id}")
	@ResponseBody
	public ResponseEntity del(@PathVariable("id") String id) {
		DeleteResponse declarationDeleteResponse = client.prepareDelete("book", "novel", id).get();
		return new ResponseEntity(declarationDeleteResponse, HttpStatus.OK);
	}

	@PutMapping("update/book/novel/{id}")
	@ResponseBody
	public ResponseEntity update(@PathVariable("id") String id, @RequestBody BookCommand book) {
		UpdateRequest update = new UpdateRequest("book", "novel", id);
		try {
			XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject();
			if (book.getAuthor() != null) {
				xContentBuilder.field("author", book.getAuthor());
			}
			if (book.getName() != null) {
				xContentBuilder.field("name", book.getName());
			}
			if (book.getPublishDate() != null) {
				xContentBuilder.field("publish_date", book.getPublishDate());
			}
			if (book.getTitle() != null) {
				xContentBuilder.field("title", book.getTitle());
			}
			if (book.getWordCount() != null) {
				xContentBuilder.field("word_count", book.getWordCount());
			}
			xContentBuilder.endObject();
			update.doc(xContentBuilder);
			UpdateResponse updateResponse = client.update(update).get();
			return new ResponseEntity(updateResponse, HttpStatus.OK);
		} catch (IOException | InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new ResponseEntity(HttpStatus.NOT_FOUND);
	}

	@PostMapping("query/book/novel")
	@ResponseBody
	public ResponseEntity query(@RequestBody BookCommand book, @RequestParam("gt_word_count") Integer gtWordCount,
			@RequestParam("lt_word_count") Integer ltWordCount) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		if (book.getAuthor() != null) {
			boolQueryBuilder.must(QueryBuilders.matchQuery("author", book.getAuthor()));
		}
		if (book.getName() != null) {
			boolQueryBuilder.must(QueryBuilders.matchQuery("name", book.getName()));
		}
		if (book.getPublishDate() != null) {
			boolQueryBuilder.must(QueryBuilders.matchQuery("publish_date", book.getPublishDate()));
		}
		if (book.getTitle() != null) {
			boolQueryBuilder.must(QueryBuilders.matchQuery("title", book.getTitle()));
		}
		RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("word_count");
		if (gtWordCount != null) {
			rangeQueryBuilder.from(gtWordCount);
		}
		if (ltWordCount != null) {
			rangeQueryBuilder.to(ltWordCount);
		}
		boolQueryBuilder.filter(rangeQueryBuilder);
		SearchResponse searchResponse = client.prepareSearch("book").setTypes("novel").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
				.setQuery(boolQueryBuilder).get();
		List<Map<String, Object>> list = new ArrayList<>();
		for (SearchHit searchHit : searchResponse.getHits()) {
			list.add(searchHit.getSource());
		}
		return new ResponseEntity(list, HttpStatus.OK);

	}
}
